package com.bharatonjava.hospital.dao.patient;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;

import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
import org.springframework.jdbc.support.SQLExceptionTranslator;

import com.bharatonjava.hospital.dao.rowMapper.AddressRowMapper;
import com.bharatonjava.hospital.dao.rowMapper.PatientRowMapper;
import com.bharatonjava.hospital.domain.Address;
import com.bharatonjava.hospital.domain.Patient;
import com.bharatonjava.hospital.utils.Constants;

public class PatientDao implements IPatientDao {

	private final Logger log = Logger.getLogger(PatientDao.class);

	private JdbcTemplate jdbcTemplate;

	@Autowired
	public void setDataSource(DataSource dataSource) {
		this.jdbcTemplate = new JdbcTemplate(dataSource);
		SQLExceptionTranslator exceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(
				dataSource);
		this.jdbcTemplate.setExceptionTranslator(exceptionTranslator);
	}

	@Override
	public int createPatient(final Patient patient, final Address address) {
		log.info("PatientDao - createPatient");
		final String sql = "Insert into patients (patient_first_name,patient_middle_name,"
				+ "patient_last_name,patient_gender, patient_dob) "
				+ " values(?,?,?,?,?)";

		final KeyHolder generatedKeyHolder = new GeneratedKeyHolder();
		int status = this.jdbcTemplate.update(new PreparedStatementCreator() {

			@Override
			public PreparedStatement createPreparedStatement(
					Connection connection) throws SQLException {
				PreparedStatement ps = connection.prepareStatement(sql,
						new String[] { "patient_Id" });
				ps.setString(1, patient.getFirstName());
				ps.setString(2, patient.getMiddleName());
				ps.setString(3, patient.getLastName());
				ps.setString(4, patient.getGender());
				java.util.Date d = new java.util.Date();
				try {
					DateFormat formatter = new SimpleDateFormat(
							Constants.DATE_FORMAT);
					d = formatter.parse(patient.getDob());
					ps.setDate(5, new java.sql.Date(d.getTime()));
				} catch (ParseException e) {
					log.error(e);
				}
				return ps;
			}
		}, generatedKeyHolder);

		log.info("Inserted Patient's id: " + generatedKeyHolder.getKey());
		final String addressSql = "INSERT INTO ADDRESSES(PATIENT_ID,BUILDING,STREET,CITY) VALUES(?,?,?,?)";

		KeyHolder addressKeyHolder = new GeneratedKeyHolder();

		int addressStatus = this.jdbcTemplate.update(
				new PreparedStatementCreator() {

					@Override
					public PreparedStatement createPreparedStatement(
							Connection connection) throws SQLException {
						PreparedStatement ps = connection.prepareStatement(
								addressSql, new String[] { "address_id" });
						ps.setLong(1, generatedKeyHolder.getKey().longValue());
						ps.setString(2, address.getBuilding());
						ps.setString(3, address.getStreet());
						ps.setString(4, address.getCity());

						return ps;
					}
				}, addressKeyHolder);

		log.info("Inserted Address Id: " + addressKeyHolder.getKey()
				+ " ; addreess Status: " + addressStatus);

		final String updateAddressIdSql = "UPDATE patients SET ADDRESS_ID=? where PATIENT_ID=?";
		this.jdbcTemplate.update(updateAddressIdSql, new Object[] {
				addressKeyHolder.getKey().longValue(),
				generatedKeyHolder.getKey().longValue() });

		log.info("Patient Status: " + status + " ; Address status: "
				+ addressStatus);
		return status;
	}

	@Override
	public Patient getPatientById(Long patientId) {
		log.info("Entering - getPatientById in DAO " + patientId);
		String sql = "select * from patients p where p.patient_id=?";
		Patient p = null;
		try {
			p = this.jdbcTemplate.queryForObject(sql, new PatientRowMapper(),
					new Object[] { patientId });
		} catch (DataAccessException e) {
			log.error(e);
		}
		log.info("p : " + p);

		return p;
	}

	@Override
	public Address getPatientAddress(Long patientId) {
		log.info("Entering - getPatientAddress in DAO " + patientId);
		String sql = "select * from addresses a where a.patient_id=?";
		Address a = null;
		try {
			a = this.jdbcTemplate.queryForObject(sql, new AddressRowMapper(),
					new Object[] { patientId });
		} catch (DataAccessException e) {
			log.error(e);
		}
		log.info("a : " + a);

		return a;
	}
	
	
	

}
